home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / Drivers / vc_2_2.lha / ParNet / Source / parnet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-02  |  9.2 KB  |  469 lines

  1. /*
  2. ** $Header: SRC:CVSROOT/Vector/ParNet/parnet.c,v 1.1.1.1 1994/06/23 02:39:39 Barnard Exp $
  3. */
  4.  
  5. /*
  6. ** This code was originally written by Matthew Dillon and put into Public Domain
  7. **
  8. ** All changes concerning the adaption of Matt's original code to the
  9. ** Vector Connection I/O board are © 1991-1994 by Henning Schmiedehausen
  10. ** All rights for this changes are reserved. The original code is Public Domain
  11. **
  12. ** This code is distributed with the expressed written permission of Matthew
  13. ** Dillon (Thank you very much, Matt)
  14. **
  15. */
  16.  
  17. /*
  18.  *  PARNET.C
  19.  *
  20.  */
  21.  
  22. #include "defs.h"
  23. #include "parnet.device_rev.h"
  24. #include "parnet_asm.h"
  25.  
  26. #include "parnet_protos.h"
  27.  
  28. #include <proto/exec.h>
  29.  
  30. #include <resources/misc.h>
  31. #include <hardware/cia.h>
  32. #include <exec/memory.h>
  33.  
  34. #include <devices/parallel.h>
  35. #include <vector/vectorpar.h>
  36.  
  37. #include <string.h>
  38. #include <stdio.h>
  39. #include <stddef.h>
  40. #include <stdlib.h>
  41.  
  42.  
  43. #define PRODUCTION
  44.  
  45. extern func_ptr DeviceVectors[];
  46. extern func_ptr UnitVectors[];
  47. extern char DeviceName[];
  48. extern char IdString[];
  49.  
  50. extern void PioInt();
  51.  
  52. extern Task *VTask;        /*  wakeup.asm    */
  53. extern long VMask;        /*  wakeup.asm    */
  54.  
  55. extern void ParNetTask();       /*  task.c      */
  56.  
  57. long    SysBase    = NULL;    /*  sysbase            */
  58. Device    *DevBase   = NULL;    /*  device base         */
  59. BPTR    DevSegment = NULL;    /*  seglist for device        */
  60. long    PLock[2]   = { 0, 0 };    /*  arbitrate network access    */
  61. PubPort *StickyPort= NULL;
  62.  
  63. char    ActiveMRPP = 0;
  64. char    ActiveMRPB = 0;
  65. char    ActiveTask = 0;
  66. char    ActiveInt  = 0;
  67.  
  68. struct Interrupt  PIOInt =
  69. {
  70.     {
  71.     NULL, NULL,
  72.     NT_INTERRUPT,
  73.     20,                        /* *WICHTIG* NICHT ÄNDERN! SO SITZT DER INTERRUPT *VOR* DEM DEVICE */
  74.     "parnet.device"
  75.     },
  76. NULL,
  77. PioInt
  78. };
  79.  
  80. struct MsgPort        *ParPort;
  81. struct IOExtPar        *ParRequest;
  82. ULONG                 UnitBase;
  83. ULONG                 PIOBase;
  84.  
  85. char                *version = VERSTAG;
  86.  
  87.  
  88.  
  89. /*
  90.  *  Init is called when the device is loaded to create it.
  91.  */
  92.  
  93. APTR
  94. CDevInit(seg)
  95. BPTR seg;
  96. {
  97.     Device *db;
  98.  
  99.     SysBase = *(long *)4;
  100.  
  101.     DevBase = db = (Device *)MakeLibrary((long **)DeviceVectors,NULL,NULL,sizeof(Device),NULL);
  102.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  103.     db->Lib.lib_Node.ln_Name = DeviceName;
  104.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  105.     db->Lib.lib_Version = VERSION;
  106.     db->Lib.lib_Revision = REVISION;
  107.     db->Lib.lib_IdString= (APTR)IdString;
  108.     db->ParAddress = 254;            /*    default address     */
  109.     db->Port.mp_Node.ln_Type = NT_MSGPORT;
  110.     db->Port.mp_SigBit = SIGBREAKB_CTRL_E;  /*    for VTask        */
  111.     db->Port.mp_Flags  = PA_SIGNAL;
  112.     NewList(&db->UnitList);
  113.     NewList(&db->Port.mp_MsgList);
  114.  
  115.     ReadConfig();
  116.     WriteConfig();
  117.  
  118.     DevSegment = seg;
  119.     AddDevice((struct Device *)db);
  120.     return((APTR)db);
  121. }
  122.  
  123. Device *
  124. CDevOpen(unitnum, flags, iob)
  125. long unitnum;
  126. long flags;
  127. Iob *iob;
  128. {
  129. #if PIO_CHANNEL == 0
  130.     int piounit = 0;
  131. #endif
  132. #if PIO_CHANNEL == 1
  133.     int piounit = 1;
  134. #endif
  135.  
  136.     Device *nd = DevBase;
  137.  
  138.     iob->io_Unit = NULL;
  139.  
  140.     LockAddr(PLock);        /*  because we make calls that kill Forbid()    */
  141.  
  142.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  143.  
  144.     if (++nd->Lib.lib_OpenCnt == 1) {
  145.     /*
  146.      *  Initial Open, allocate resources
  147.      */
  148.  
  149.     if(!(ParPort = (struct MsgPort *)CreatePort("PIONet-Port",NULL)))
  150.     {
  151.         goto badop;
  152.     }
  153.     if(!(ParRequest = (struct IOExtPar *)CreateExtIO(ParPort, sizeof(struct IOExtPar))))
  154.     {
  155.         goto badop;
  156.     }
  157.  
  158.     if(OpenDevice(PARALLELDEVICE, piounit, ParRequest, NULL))
  159.     {
  160.         goto badop;
  161.     }
  162.  
  163. #ifndef DEBUG
  164.     ParRequest->IOPar.io_Command = PIOCMD_INACTIVE;            /* Unit abklemmen */
  165.     DoIO(ParRequest);
  166.     UnitBase = (ULONG)ParRequest->IOPar.io_Actual;
  167.     PIOBase  = (ULONG)ParRequest->IOPar.io_Length;
  168.  
  169. #else
  170.  
  171.     UnitBase = 0xe94001;
  172.     PIOBase  = 0xe94001;
  173.  
  174. #endif
  175.  
  176.  
  177.     VTask = (struct Task *)CreateTask("parnet.device", 0, (APTR)ParNetTask, 4096);
  178.     if (VTask == NULL) {
  179.         iob->io_Actual = PPERR_NOTASK;
  180.         goto badop;
  181.     }
  182.     ActiveTask = 1;
  183.     VMask = SIGBREAKF_CTRL_F;
  184.     nd->Port.mp_SigTask = VTask;    /*  for asynchronous I/O    */
  185.  
  186.     ClearPIOInt();            /* ev. pending PIO Interrupts löschen */
  187.  
  188.     AddIntServer(PIO_INTERRUPT, &PIOInt);
  189.  
  190.     SetUpPIO();
  191.  
  192.     ActiveInt = 1;
  193.  
  194.     if (DetermineTimeouts() < 0)    /*  couldn't use timer.device   */
  195.         goto badop;
  196.  
  197.     }
  198.     iob->io_Actual= 0;
  199.     iob->io_Error = 0;
  200.  
  201.     /*
  202.      *    Attempt to open the specified unit by protocol
  203.      */
  204.  
  205.     {
  206.     short proto = iob->io_Flags & PRO_MASK;
  207.  
  208.     if (proto <= PRO_LAST) {
  209.         (*UnitVectors[proto])(iob, unitnum, flags);
  210.         if (iob->io_Error == 0) {
  211.         UnlockAddr(PLock);
  212.         return(nd);
  213.         }
  214.     }
  215.     }
  216.  
  217.     /*
  218.      *    OPEN FAILED
  219.      */
  220.  
  221. badop:
  222.     CDevClose(iob);
  223.     iob->io_Actual = iob->io_Error;
  224.     iob->io_Error  = IOERR_OPENFAIL;
  225.     UnlockAddr(PLock);
  226.     return(NULL);
  227. }
  228.  
  229. CDevExpunge()
  230. {
  231.     Device *nd = DevBase;
  232.     BPTR ds = DevSegment;
  233.  
  234.     if (ds == NULL)
  235.     Alert(24);
  236.  
  237.     if (nd->Lib.lib_OpenCnt) {              /*  delayed expunge */
  238.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  239.     return(NULL);
  240.     }
  241.     Remove((NODE *)nd);
  242.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  243.     DevSegment = NULL;
  244.     return(ds);
  245. }
  246.  
  247. BPTR
  248. CDevClose(iob)
  249. Iob *iob;
  250. {
  251.     Device *nd = DevBase;
  252.  
  253.     if (iob->io_Unit)
  254.     (*iob->io_Unit->CloseFunc)(iob);
  255.  
  256.     iob->io_Unit   = NULL;            /*  clear vectors    */
  257.     iob->io_Device = NULL;
  258.  
  259.     if (nd->Lib.lib_OpenCnt == 1)   {           /*  last close          */
  260.     if (ActiveInt)
  261.  
  262.     {
  263.     ClearPIOInt();
  264.  
  265.     RemIntServer(PIO_INTERRUPT, &PIOInt);
  266.  
  267.     }
  268.     if (ActiveTask)
  269.         RemTask(VTask);
  270.  
  271. #ifndef DEBUG
  272.     ParRequest->IOPar.io_Command = PIOCMD_ACTIVE;        /* Port wieder fürs Device */
  273.     DoIO(ParRequest);
  274. #endif
  275.  
  276.     CloseDevice(ParRequest);
  277.     DeleteExtIO(ParRequest);
  278.     DeletePort(ParPort);
  279.  
  280.     ActiveInt = 0;
  281.     ActiveTask= 0;
  282.     ActiveMRPB= 0;
  283.     ActiveMRPP= 0;
  284.     }
  285.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  286.     return(NULL);                           /*  still has refs      */
  287.  
  288.     /*
  289.      *    Note: LIBF_DELEXP never set if DevClose() called from DevOpen()
  290.      */
  291.  
  292.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  293.     return(CDevExpunge());                  /*  expunge             */
  294.     return(NULL);                               /*  no expunge          */
  295. }
  296.  
  297. /*
  298.  *  UNITS
  299.  */
  300.  
  301. Unit *UnitCache = NULL;
  302.  
  303. Unit *
  304. FindUnitForPort(port)
  305. uword port;
  306. {
  307.     Unit *unit;
  308.     Device *db;
  309.  
  310.     if (UnitCache && port == UnitCache->Port)
  311.     return(UnitCache);
  312.  
  313.     db = DevBase;
  314.     for (unit = (Unit *)db->UnitList.lh_Head; unit != (Unit *)&db->UnitList.lh_Tail; unit = (Unit *)unit->Node.ln_Succ) {
  315.     if (port == unit->Port) {
  316.         UnitCache = unit;
  317.         return(unit);
  318.     }
  319.     }
  320.     return(NULL);
  321. }
  322.  
  323. Unit *
  324. AllocUnit(iob, beginFunc, abortFunc, dataFunc, closeFunc)
  325. Iob *iob;
  326. func_void beginFunc;
  327. func_void abortFunc;
  328. func_void dataFunc;
  329. func_void closeFunc;
  330. {
  331.     Unit *unit = (Unit *)AllocMem(sizeof(Unit), MEMF_CLEAR | MEMF_PUBLIC);
  332.     Device *db = DevBase;
  333.  
  334.     unit->BeginIO = beginFunc;
  335.     unit->AbortIO = abortFunc;
  336.     unit->CloseFunc = closeFunc;
  337.     unit->DataFunc = dataFunc;
  338.  
  339.     unit->Port = iob->io_Port;
  340.     unit->Protocol = iob->io_Flags & PRO_MASK;
  341.     unit->DestAddr = iob->io_Addr;
  342.  
  343.     NewList(&unit->PendIOR);
  344.     NewList(&unit->PendIOW);
  345.     NewList(&unit->PendCon);
  346.     NewList(&unit->PendLsn);
  347.  
  348.     AddHead(&db->UnitList, (struct Node *)unit);
  349.  
  350.     return(unit);
  351. }
  352.  
  353. void
  354. FreeUnit(unit)
  355. Unit *unit;
  356. {
  357.     Remove(&unit->Node);
  358.     FreeMem(unit, sizeof(Unit));
  359.     UnitCache = NULL;
  360. }
  361.  
  362. /*
  363.  *  Packets
  364.  */
  365.  
  366. Packet *
  367. AllocParPacket(iob, unit, data1, bytes1, data2, bytes2)
  368. Iob *iob;
  369. Unit *unit;
  370. ubyte *data1;
  371. ubyte *data2;
  372. long bytes1;
  373. long bytes2;
  374. {
  375.     Packet *packet = (Packet *)AllocMem(sizeof(Packet), MEMF_CLEAR|MEMF_PUBLIC);
  376.  
  377.     packet->iob = iob;
  378.     packet->io_Unit = unit;
  379.     if (iob)
  380.     packet->DestAddr = iob->io_Addr;
  381.     packet->DestPort = unit->Port;
  382.     packet->Data1 = data1;
  383.     packet->Data2 = data2;
  384.     packet->DLen1 = bytes1;
  385.     packet->DLen2 = bytes2;
  386.  
  387.     return(packet);
  388. }
  389.  
  390. void
  391. FreeParPacket(packet)
  392. Packet *packet;
  393. {
  394.     FreeMem(packet, sizeof(Packet));
  395. }
  396.  
  397. /*
  398.  *                CONFIG
  399.  */
  400.  
  401. void
  402. ReadConfig()
  403. {
  404.     PubPort *port;
  405.  
  406.     if ((port = StickyPort) == NULL)
  407.     port = (PubPort *)FindPort(PORTNAME);
  408.  
  409.     if (port) {
  410.     DevBase->ParAddress = port->Address;
  411.     ParAddress(DevBase->ParAddress);
  412.     /*ParLLTimeout = port->Timeout;*/
  413.     }
  414.     StickyPort = port;
  415. }
  416.  
  417. void
  418. WriteConfig()
  419. {
  420.     char *portName = PORTNAME;
  421.     PubPort *port;
  422.  
  423.     if ((port = StickyPort) == NULL && (port = (PubPort *)FindPort(portName)) == NULL) {
  424.     port = (PubPort *)AllocMem(sizeof(PubPort) + strlen(portName) + 1, MEMF_PUBLIC | MEMF_CLEAR);
  425.     port->Port.mp_Node.ln_Name = (char *)(port + 1);
  426.  
  427.     strcpy(port->Port.mp_Node.ln_Name, portName);
  428.     port->Port.mp_Node.ln_Type = NT_MSGPORT;
  429.     port->Port.mp_Node.ln_Pri  = 0;
  430.     NewList(&port->Port.mp_MsgList);
  431.     AddPort((PORT *)port);
  432.     }
  433.     port->Address = DevBase->ParAddress;
  434.     port->Timeout = ParLLTimeout;
  435.     StickyPort = port;
  436. }
  437.  
  438. /*
  439.  *  Determines the processor speed for soft wired timeouts in PAR.ASM
  440.  *  by timing 1 second.
  441.  */
  442.  
  443. DetermineTimeouts()
  444. {
  445.     IOT iot;
  446.     long cnt = 0;
  447.     PORT *port = (PORT *)CreatePort(NULL, 0);
  448.  
  449.     if (OpenDevice(TIMERNAME, UNIT_VBLANK, &iot, 0))
  450.     return(-1);
  451.     iot.tr_node.io_Command = TR_ADDREQUEST;
  452.     iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  453.     iot.tr_node.io_Message.mn_ReplyPort = port;
  454.     iot.tr_time.tv_secs = 1;
  455.     iot.tr_time.tv_micro= 0;
  456.     SendIO(&iot);
  457.     while (CheckIO(&iot) == NULL) {
  458.     Time10000();
  459.     cnt += 10000;
  460.     }
  461.     WaitIO(&iot);
  462.     ParLLTimeout = cnt;
  463.     CloseDevice(&iot);
  464.     DeletePort(port);
  465.     return(0);
  466. }
  467.  
  468.  
  469.